package cn.kennylee.codehub.mq.lip.integration.base;

import cn.hutool.core.date.SystemClock;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.lang.NonNull;

import java.time.ZonedDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 标准化消息VO
 * <p>Created on 2024/12/16.</p>
 *
 * @author kennylee
 * @since 0.0.1
 */
@Data
@Accessors(chain = true)
public class MessageVo {

    /**
     * 业务数据为基础类型数，JSONObject存放的属性名
     */
    public static final String DATA_VALUE_PROP = "value";

    /**
     * 消息hasHey，非必填，不同消息可重复，特定中间件支持；可以理解成业务ID，例如订单ID，用户ID等
     * <p>主要作用：控制消息路由（决定进入哪个队列），顺序消费时建议必填</p>
     * <p>业务作用：可以快速定位消息相关数据</p>
     */
    private String hashKey;

    /**
     * 业务数据体
     */
    private JSON data;

    /**
     * 发送消息时间原始时间，时间戳，1970-01-01 00:00:00 UTC开始的毫秒数
     */
    private Long sendMsgDatetime = SystemClock.now();

    /**
     * 消息头
     */
    private Map<String, String> headers;

    /**
     * 扩展信息
     */
    private Map<String, String> extra;

    public static MessageVo of(JSON data) {
        return MessageVo.Builder.of(data).build();
    }

    public static MessageVo of(@NonNull Object object) {
        if (object instanceof String || object instanceof Number || object instanceof Boolean) {
            // 如果是基本类型，直接包装为 JSONObject
            return MessageVo.Builder.of(new JSONObject().set(DATA_VALUE_PROP, object)).build();
        }
        JSONConfig jsonConfig = JSONConfig.create().setIgnoreNullValue(true);
        return MessageVo.Builder.of(JSONUtil.parse(object, jsonConfig)).build();
    }

    /**
     * 将消息体转换为指定类型的对象
     *
     * @param <T> 指定类型
     * @return 转换后的对象
     */
    public <T> List<T> getDataToList() {
        return this.data.toBean(new TypeReference<>() {
        });
    }

    /**
     * 将消息体转换为指定类型的对象
     *
     * @param <T> 指定类型
     * @return 转换后的对象
     */
    public <T> Set<T> getDataToSet() {
        return this.data.toBean(new TypeReference<>() {
        });
    }

    public static class Builder {
        /**
         * 消息hasHey，可以使用业务ID，例如订单ID等
         */
        private String hashKey;

        /**
         * 业务数据体
         */
        private final JSON data;

        /**
         * 发送消息时间原始时间
         */
        private ZonedDateTime sendMsgDatetime;

        /**
         * 扩展信息
         */
        private Map<String, String> extra;

        /**
         * 消息头
         */
        private Map<String, String> headers;

        private Builder(JSON data) {
            this.data = data;
        }

        public static Builder of(JSON data) {
            return new Builder(data);
        }

        public static Builder of(Object object) {
            return of(JSONUtil.parse(object));
        }

        public Builder hashKey(String hashKey) {
            this.hashKey = hashKey;
            return this;
        }

        public Builder sendMsgDatetime(ZonedDateTime sendMsgDatetime) {
            this.sendMsgDatetime = sendMsgDatetime;
            return this;
        }

        public Builder headers(Map<String, String> headers) {
            this.headers = headers;
            return this;
        }

        public Builder extra(Map<String, String> extra) {
            this.extra = extra;
            return this;
        }

        public MessageVo build() {
            MessageVo messageVo = new MessageVo();
            messageVo.setHashKey(hashKey)
                .setData(data)
                .setHeaders(headers)
                .setExtra(extra);
            if (Objects.nonNull(sendMsgDatetime)) {
                messageVo.setSendMsgDatetime(sendMsgDatetime.toInstant().toEpochMilli());
            }
            return messageVo;
        }
    }
}
